import pyecharts
from pyecharts.charts import Map, Geo, Timeline, Line, Tab, Bar
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
from datetime import date, datetime
import webbrowser
import json
import pandas as pd
import datetime
import numpy as np


# 读取数据
def load(path):
    '''
    根据路径加载数据
    :param path:对应路径
    '''
    with open(path, encoding="utf-8") as fp:
        data = json.load(fp)
    return data


data = load('data/metadata/area_data_day.json')
update_date = date.today()


# 世界地图
def map_of_the_world():
    oversea_confirm = []
    for item in data['results']:
        if item['countryEnglishName']:
            oversea_confirm.append((item['countryEnglishName'].replace('United States of America', 'United States')
                                    .replace('United Kiongdom', 'United Kingdom'),
                                    item['confirmedCount']))

    _map = (
        Map(init_opts=opts.InitOpts(theme='dark', width='100%', height='90vh'))
            .add("累计确诊人数", oversea_confirm, "world", is_map_symbol_show=False, is_roam=False)
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .set_global_opts(
            title_opts=opts.TitleOpts(title="新型冠状病毒全球疫情地图",
                                      subtitle="更新日期：{}".format(update_date)),
            legend_opts=opts.LegendOpts(is_show=False),
            visualmap_opts=opts.VisualMapOpts(is_show=True, max_=5000000,
                                              is_piecewise=False,
                                              range_color=['#F08080', '#CD5C5C', '#FF0000', '#A52A2A', '#B22222']),
            graphic_opts=[
                opts.GraphicGroup(
                    graphic_item=opts.GraphicItem(
                        bounding="raw",
                        right=150,
                        bottom=50,
                        z=100,
                    ),
                    children=[
                        opts.GraphicRect(
                            graphic_item=opts.GraphicItem(
                                left="center", top="center", z=100
                            ),
                            graphic_shape_opts=opts.GraphicShapeOpts(
                                width=200, height=50
                            ),
                            graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                fill="rgba(0,0,0,0.3)"
                            ),
                        ),
                        opts.GraphicText(
                            graphic_item=opts.GraphicItem(
                                left="center", top="center", z=100
                            ),
                            graphic_textstyle_opts=opts.GraphicTextStyleOpts(
                                text=JsCode("['中国', '累计确诊人数：{}人'].join('\\n')"
                                            .format(dict(oversea_confirm)['Diamond Princess Cruise Ship'])),
                                font="bold 16px Microsoft YaHei",
                                graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                    fill="#fff"
                                ),
                            ),
                        ),
                    ],
                )
            ],
        )
    )
    _map.render("map_of_the_world.html")
    webbrowser.open('map_of_the_world.html')


# 中国地图
def map_of_china_hot():
    cities_data = []
    for item in data['results']:
        if item['countryName'] == '中国':
            if item['cities'] is not None:
                cities_data.extend((item['cities']))
    print(cities_data)
    geo = (
        Geo(init_opts=opts.InitOpts(theme='dark', width='100%', height='90vh'))
            .add_schema(maptype="china", zoom=3, center=[114.31, 30.52])
            .add("累计确诊人数",
                 [(i['cityName'], i['confirmedCount']) for i in cities_data
                  if i['cityName'] in pyecharts.datasets.COORDINATES.keys()],
                 type_='heatmap',
                 symbol_size=3,
                 progressive=50)
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .set_global_opts(
            title_opts=opts.TitleOpts(title="新型冠状病毒全国疫情热力图",
                                      subtitle="更新日期：{}".format(update_date),
                                      pos_left='right'),
            legend_opts=opts.LegendOpts(is_show=False),
            visualmap_opts=opts.VisualMapOpts(is_show=True,
                                              is_piecewise=False,
                                              range_color=['blue', 'green', 'yellow', 'yellow', 'red'])
        )
    )

    geo.render("map_of_china_hot.html")
    webbrowser.open('map_of_china_hot.html')


words_data = pd.read_csv("data/metadata/currentConfirmedCount.csv", index_col=0)
area_data_timeline = load("data/metadata/area_data_day.json")
all_data_timeline = load("data/metadata/DXYOverall.json")


def get_value(dic, key):
    try:
        return dic[key]
    except KeyError:
        return 0


def insert_data(to_update_date, to_update_area, dic, is_city):
    if to_update_date in format_data:
        if to_update_area in format_data[to_update_date]:
            pass
        else:
            format_data[to_update_date][to_update_area] = {}
    else:
        format_data[to_update_date] = {}
        format_data[to_update_date][to_update_area] = {}
    format_data[to_update_date][to_update_area]['currentConfirmedCount'] = get_value(dic, 'currentConfirmedCount')
    format_data[to_update_date][to_update_area]['confirmedCount'] = get_value(dic, 'confirmedCount')
    format_data[to_update_date][to_update_area]['deadCount'] = get_value(dic, 'deadCount')
    format_data[to_update_date][to_update_area]['suspectedCount'] = get_value(dic, 'suspectedCount')
    format_data[to_update_date][to_update_area]['curedCount'] = get_value(dic, 'curedCount')
    format_data[to_update_date][to_update_area]['countryName'] = get_value(dic, 'countryName')
    # 用于区分区域层级
    if is_city:
        format_data[to_update_date][to_update_area]['is_city'] = 1
    else:
        format_data[to_update_date][to_update_area]['is_city'] = 0


format_data = {}
for item in area_data_timeline['results'][::-1]:
    to_update_date = date.fromtimestamp(item['updateTime'] / 1000)
    to_update_area = item['provinceShortName']
    insert_data(to_update_date, to_update_area, item, 0)
    if 'cities' in item:
        if item['cities']:
            for city_data in item['cities']:
                insert_data(to_update_date, city_data['cityName'], city_data, 1)

for item in all_data_timeline[::-1]:
    to_update_date = date.fromtimestamp(item['updateTime'] / 1000)
    insert_data(to_update_date, '全国', item, 0)

time_range = list(format_data.keys())


def area_data(area_name='广东', type_='confirmedCount', get_total=True, date_list=time_range):
    # 用于pyecharts获取时间序列数据
    data_array = []
    for day in date_list:
        try:
            data_array.append(format_data[day][area_name][type_])
        except KeyError:
            if day + datetime.timedelta(days=-1) in format_data:
                if area_name in format_data[day + datetime.timedelta(days=-1)]:
                    # 当天未更新数据情况时，取前一天数据填充
                    data_array.append(format_data[day + datetime.timedelta(days=-1)][area_name][type_])
                else:
                    data_array.append(0)
            else:
                data_array.append(0)
    # 返回每日新增数据
    if not get_total:
        data_array = [data_array[i + 1] - data_array[i] for i in range(len(data_array) - 1)]
    return data_array


# 中国疫情趋势图
def guangzhou_china():
    print(area_data_timeline)
    data_type = {'累计确诊': 'confirmedCount',
                 '死亡病例': 'deadCount',
                 '治愈病例': 'curedCount'}

    tl = Timeline(init_opts=opts.InitOpts(theme='dark', width='100%', height='90vh'))
    tl.add_schema(is_auto_play=True, play_interval=5000)
    for key_, value_ in data_type.items():
        line = (Line(init_opts=opts.InitOpts())
            .add_xaxis(time_range)
            .add_yaxis("全国", area_data('全国', value_), is_smooth=True,
                       areastyle_opts=opts.AreaStyleOpts(opacity=1,
                                                         color=JsCode("""new echarts.graphic.LinearGradient(0, 0, 0, 1, 
                                                                            [{
                                                                                offset: 0,
                                                                                color: '#00FFFF'
                                                                            }, {
                                                                                offset: 1,
                                                                                color: '#00FF7F'
                                                                            }])""")),
                       markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="最新数据")],
                                                         symbol_size=70))
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .set_global_opts(
            title_opts=opts.TitleOpts(title="新型冠状病毒全国{}趋势图".format(key_),
                                      subtitle="更新日期：{}".format(update_date)),
            xaxis_opts=opts.AxisOpts(
                type_="time",
                splitline_opts=opts.SplitLineOpts(is_show=False)),
        ))
        tl.add(line, key_)

    tl.render_notebook()

    tl.render("guangzhou_china.html")
    webbrowser.open('guangzhou_china.html')


# 全国疫情新增趋势
def the_new_trend():
    line = (Line(init_opts=opts.InitOpts(theme='dark', width='100%', height='90vh'))
        .add_xaxis(time_range[1:])
        .add_yaxis("全国", area_data('全国', get_total=False), is_smooth=True,
                   areastyle_opts=opts.AreaStyleOpts(opacity=1,
                                                     color=JsCode("""new echarts.graphic.LinearGradient(0, 0, 0, 1, 
                                                                        [{
                                                                            offset: 0,
                                                                            color: 'rgb(255,99,71)'
                                                                        }, {
                                                                            offset: 1,
                                                                            color: 'rgb(32,178,170)'
                                                                        }])""")), )
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
        title_opts=opts.TitleOpts(title="新型冠状病毒全国每日新增确诊病例趋势图",
                                  subtitle="更新日期：{}".format(update_date)),
        xaxis_opts=opts.AxisOpts(
            type_="time",
            splitline_opts=opts.SplitLineOpts(is_show=False)),
    ))
    line.render("the_new_trend.html")
    webbrowser.open('the_new_trend.html')


corona_virus_data = pd.read_json("data/metadata/corona_virus.json")


def get_values_countries(area_name, type_):
    dataframe = pd.DataFrame(corona_virus_data)
    data_frame = dataframe[dataframe['provinceName'] == area_name]
    data_frame = data_frame[[type_]]
    data_frame_list = [num for elem in data_frame.values for num in elem]
    return list(data_frame_list[-211::15])

confirmed = None
# 海外主要国家确诊/治愈率/死亡率趋势
def major_overseas_countries():
    country_list = ['中国', '美国', '日本', '印度', '意大利']
    frame = pd.DataFrame(words_data)
    index_date = str(frame.index[-1])
    date_list = [datetime.date(int(index_date[0:4]), int(index_date[4:6]), int(index_date[6:8])) + datetime.timedelta(
        days=-i) for i in range(211)][::-15]
    tab = Tab()
    global confirmed
    for country in country_list:
        confirmed = get_values_countries(area_name=country, type_='confirmedCount')
        dead = get_values_countries(area_name=country, type_='deadCount')
        cured = get_values_countries(area_name=country, type_='curedCount')
        dead_rate = [i / j if j != 0 else 0. for i, j in zip(dead, confirmed)]
        cure_rate = [i / j if j != 0 else 0. for i, j in zip(cured, confirmed)]
        line = (Line(init_opts=opts.InitOpts(theme='dark', width='100vw', height='90vh'))
            .add_xaxis(date_list)
            .add_yaxis("死亡率", dead_rate, yaxis_index=1, is_smooth=True, color='red')
            .add_yaxis("治愈率", cure_rate, yaxis_index=1, is_smooth=True, color='green')
            .extend_axis(yaxis=opts.AxisOpts(
            name="",
            type_="value",
            min_=0,
            max_=1,
            position="right",
            axislabel_opts=opts.LabelOpts(
                formatter=JsCode("""function (value) 
                                                        {return Number(value *100)+'%';}""")), )
        )
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .set_global_opts(
            title_opts=opts.TitleOpts(title="【{}】确诊/治愈率/死亡率 趋势".format(country),
                                      subtitle="更新日期：{}".format(update_date)),
            tooltip_opts=opts.TooltipOpts(formatter=JsCode("""function (params) 
                                                        {return Number(params.value[1] *100).toFixed(3)+'%';}""")),
            xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
            legend_opts=opts.LegendOpts(is_show=True)
        )
        )
        bar = (Bar()
               .set_series_opts(label_opts=opts.LabelOpts(is_show=True,
                                                          position='top',
                                                          font_style='italic'),
                                itemstyle_opts=opts.ItemStyleOpts(opacity=0.8,
                                                                  color=JsCode("""new echarts.graphic.LinearGradient
                                                    (0, 0, 0, 1, 
                                                     [{
                                                         offset: 0,
                                                         color: 'rgb(255,99,71)'
                                                     }, {
                                                         offset: 1,
                                                         color: 'rgb(32,178,170)'
                                                     }])""")),
                                min_=min(confirmed),
                                max_=max(confirmed),

                                )
               )
        print(confirmed)
        bar.add_xaxis(time_range)
        bar.add_yaxis(series_name="确诊病例", y_axis=confirmed, yaxis_index=0)
        line.overlap(bar)

        tab.add(line, country)
    tab.render("major_overseas_countries.html")
    webbrowser.open('major_overseas_countries.html')

